/**
 *
 */
package com.naiterui.ehp.bs.doctor.interceptor;

import com.naiterui.ehp.bp.support.exception.PublicService;
import com.naiterui.ehp.bp.support.security.HeaderConstant;
import com.naiterui.ehp.bp.support.utils.JsonMapper;
import com.naiterui.ehp.bs.doctor.exception.ExceptionCodes;
import com.naiterui.ehp.bs.doctor.utils.VersionUtil;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 版本升级拦截器
 * @author guoyongxiang
 * @since 1.0.0
 */
public class VersionInterceptor implements HandlerInterceptor {

    /**
     * 不校验版本升级接口列表
     */
    private static final String[] NOCHECK_VERSION_URI = {"/ad/checkVersion", "/ad/saveVersion", "/ad/saveH5Version",};

    private static final Integer[] CHECK_VERSION_ORIGIN = {
            // 医生APP
            HeaderConstant.HEADER_ORIGIN_DOCTOR_APP,
            // 患者APP
            HeaderConstant.HEADER_ORIGIN_PATIENT_APP};

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // ************************************Header 参数获取**************************************
        // 平台
        String platform = request.getHeader(HeaderConstant.HEADER_PLATFORM);
        // 来源
        String origin = request.getHeader(HeaderConstant.HEADER_ORIGIN);
        // 客户端版本
        String version = request.getHeader(HeaderConstant.HEADER_VERSION);

        // URL
        String url = request.getServletPath();

        // ************************************ 升级校验 ************************************
        // 需要检查版本升级应用来源列表
        if (!checkVersionOrigin(origin)) {
            return true;
        }

        // 忽略版本升级接口列表
        if (checkVersionIgnoreUrl(url)) {
            return true;
        }

        // (安卓||IOS) && (患者APP||医生APP PS:忽略列表已排除其他来源)
        if ((HeaderConstant.HEADER_PLATFORM_ANDROID_PHONE + "").equals(platform)
                || (HeaderConstant.HEADER_PLATFORM_IOS_PHONE + "").equals(platform)) {

            // APP版本校验升级
            if (version == null || VersionUtil.compareDoctorVerNameAndPlat(version, platform)) {
                response.getWriter().println(JsonMapper.toJson(PublicService.returnResponseVO(ExceptionCodes.DR_MANDATORY_UPGRADE)));
                return false;
            }

        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

    }

    /**
     * 校验免升级校验列表
     * LoginInterceptor.checkVersionIgnoreUrl()
     * @Author guoyongxiang
     * @Date 2017年6月28日
     * @since 2.8.0
     * @param reqUrl
     * @return
     */
    private static boolean checkVersionIgnoreUrl(String reqUrl) {
        for (String uri : NOCHECK_VERSION_URI) {
            if (matchUrl(uri, reqUrl)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 检查是否为需要版本升级校验的应用来源
     * LoginInterceptor.checkVersionOrigin()
     * @Author guoyongxiang
     * @Date 2017年7月4日
     * @since 2.8.0
     * @param origin
     * @return
     */
    private static boolean checkVersionOrigin(String origin) {
        for (Integer checkOrigin : CHECK_VERSION_ORIGIN) {
            if ((checkOrigin + "").equals(origin)) {
                return true;
            }
        }
        return false;

    }

    /**
     * 匹配URL
     * LoginInterceptor.matchUrl()
     * @Author guoyongxiang
     * @Date 2017年6月28日
     * @since 2.8.0
     * @param matchUrl 匹配规则(左匹配支持*)
     * @param reqUrl 被检测URL
     * @return
     */
    private static boolean matchUrl(String matchUrl, String reqUrl) {
        Pattern pattern = Pattern.compile(matchUrl);
        Matcher matcher = pattern.matcher(reqUrl);
        return matcher.lookingAt();
    }

}
